<template lang="">
  <div>
    <el-card style="margin:20px 0">
      <CategorySelect :show="!isShowTable" @getCategoryId="getCategoryId" />
    </el-card>
    <el-card>
      <div v-show="isShowTable">
        <el-button type="primary" icon="el-icon-plus" :disabled="!category3Id" @click="addAttr">添加属性</el-button>
        <el-table style="width: 100%;margin-top:10px" border :data="attrList">
          <el-table-column type="index" label="序号" prop="" align="center" width="80px" />
          <el-table-column label="属性名称" prop="attrName" width="150px" />
          <el-table-column label="属性值列表" prop="" width="width">
            <template slot-scope="{row, $index}">
              <div>
                <el-tag v-for="(attrValue, index) in row.attrValueList" :key="attrValue.id" type="success" style="margin:2px 10px">{{ attrValue.valueName }}</el-tag>
              </div>
            </template>
          </el-table-column>
          <el-table-column label="操作" prop="" width="150px">
            <template slot-scope="{row, $index}">
              <div>
                <el-button type="warning" icon="el-icon-edit" size="mini" @click="updateAttr(row)" />
                <el-button type="danger" icon="el-icon-delete" size="mini" @click="deleteAttr(row)" />
              </div>
            </template>
          </el-table-column>
        </el-table>
      </div>
      <!-- 添加属性或者修改属性的结构 -->
      <div v-show="!isShowTable">
        <el-form ref="form" :model="attrInfo" :inline="true" label-width="80px">
          <el-form-item label="属性名">
            <el-input v-model="attrInfo.attrName" placeholder="请输入属性名" />
          </el-form-item>
        </el-form>
        <el-button type="primary" icon="el-icon-plus" :disabled="!attrInfo.attrName" @click="addAttrValue">添加属性值</el-button>
        <el-button @click="isShowTable=true">取消</el-button>
        <el-table style="width:100%;margin:20px 0px" border :data="attrInfo.attrValueList">
          <el-table-column type="index" label="序号" width="80px" align="center" />
          <el-table-column label="属性值名称" prop="prop" width="width">
            <template slot-scope="{row, $index}">
              <div>
                <!-- 这里的结构需要用到span与input进行来回的切换 -->
                <el-input v-if="row.flag" :ref="$index" v-model="row.valueName" placeholder="请输入属性值名称" size="mini" @blur="toLook(row)" @keyup.native.enter="toLook(row)" />
                <span v-else style="display: block" @click="toEdit(row, $index)">{{ row.valueName }}</span>
              </div>
            </template>
          </el-table-column>
          <el-table-column label="操作" prop="prop" width="width">
            <template slot-scope="{row,$index}">
              <!-- 气泡确认框 -->
              <el-popconfirm :title="`确定删除${row.valueName}吗？`" @onConfirm="deleteAttrValue($index)">
                <el-button slot="reference" type="danger" icon="el-icon-delete" size="mini">删除</el-button>
              </el-popconfirm>
            </template>
          </el-table-column>
        </el-table>
        <el-button type="primary" :disabled="attrInfo.attrValueList.length<1" @click="addOrUpdateAttr">保存</el-button>
        <el-button @click="isShowTable=true">取消</el-button>
      </div>
    </el-card>
  </div>
</template>
<script>
// 按需引入lodash中的深拷贝
import cloneDeep from 'lodash/cloneDeep'
export default {
  name: 'Attr',
  data() {
    return {
      category1Id: '',
      category2Id: '',
      category3Id: '',
      // 接收平台属性的字段
      attrList: [],
      // 这个属性控制table表格显示与隐藏
      isShowTable: true,
      // 收集新增属性 |或者修改属性使用的
      attrInfo: {
        attrName: '', // 属性名
        attrValueList: [], // 属性名中的属性值，因为属性值可以是多个，因此需要的是数组，每一个属性值都是一个对象需要attrId、valueName
        categoryId: 0, // 三级分类的id
        categoryLevel: 3 // 因为服务器也需要区分几级id
      }
    }
  },
  methods: {
    // 自定义事件的回调 子->父
    getCategoryId({ categoryId, level }) {
      console.log(`子组件传递来的${level}级id`, categoryId)
      // 区分三级分类相应的id，以及父组件进行存储
      if (level == 1) {
        this.category1Id = categoryId
        // 一级分类的id变化， 二级、三级分类的id清空
        this.category2Id = ''
        this.category3Id = ''
      } else if (level == 2) {
        this.category2Id = categoryId
        // 二级分类的id变化，三级分类的id清空
        this.category3Id = ''
      } else {
        // 代表三级分类的id有了
        this.category3Id = categoryId
        // 发请求获取平台的属性数据
        this.getAttrList()
      }
    },
    // 获取平台属性的数据
    // 当用户确定三级分类的数据时候，可以向服务器发送请求获取平台属性进行展示
    async getAttrList() {
      // console.log('发请求')
      // 获取分类的ID
      const { category1Id, category2Id, category3Id } = this
      const result = await this.$API.attr.reqAttrList(category1Id, category2Id, category3Id)
      console.log('获取属性的列表', result)
      if (result.code == 200) {
        this.attrList = result.data
      }
    },
    // 添加属性按钮的回调
    addAttr() {
      // 切换tab的显示隐藏
      this.isShowTable = false
      // 清除数据， 防止数据回显
      this.attrInfo = {
        attrName: '', // 属性名
        attrValueList: [], // 属性名中的属性值，因为属性值可以是多个，因此需要的是数组，每一个属性值都是一个对象需要attrId、valueName
        categoryId: this.category3Id, // 重新收集三级分类的id
        categoryLevel: 3 // 因为服务器也需要区分几级id
      }
    },
    // 添加属性值的函数
    addAttrValue() {
      console.log(111)
      // 向属性值的数组里面添加元素 push
      // attrId：是你相应的属性的id，目前而言我们是添加属性的操作，还没有相应的属性的id，目前而言带给服务器的id为undefined
      // valueName：相应的属性值的名称
      this.attrInfo.attrValueList.push({
        // 对于修改某一个属性的时候，可以在已有的属性值基础之上，可以再次进行新增操作，这时需要把已有的属性的id带上
        // 在 新增的时候attrInfo没有id，带的就是undefined，在修改的时候有id，带上attrInfo里面的id
        attrId: this.attrInfo.id,
        valueName: '',
        // 给每一个属性值都加一个flag，进行控制判断，用于切换查看模式与编辑模式。好处：每一个属性值可以控制自己的模式切换
        // 当前这个flag是一个响应式属性（数据变化，视图跟着变化）
        flag: true
      })
      this.$nextTick(() => {
        // 数组中的最后一项，即为数组长度 -1
        this.$refs[this.attrInfo.attrValueList.length - 1].focus()
      })
    },
    // 修改某一个属性按钮
    updateAttr(row) {
      this.isShowTable = false
      // 因为这里数据中有attrValueList: []，里面又是对象，又嵌套了一层，要用深拷贝解决
      // 由于数据结构当中，存在对象里面套数组，数组里面又套了对象，因此需要使用深拷贝解决这类问题
      this.attrInfo = cloneDeep(row)
      // 在修改某一个属性的时候，将相应的属性值元素添加上flag这个标记
      this.attrInfo.attrValueList.forEach(item => {
        // 这样书写可以给属性值自动添加flag，但是会发现试图不会跟着变化（因为flag不是响应式数据）
        // 因为vue无法探测普通的新增prototype，这样书写的属性值并非响应式属性（数据变化、视图跟着变化）
        // item.flag = false
        // 为了给数据添加响应式的flag,用$set
        // 第一个参数：对象，第二个参数：添加新的响应式属性，第三个参数：新的属性的属性值
        this.$set(item, 'flag', false)
      })
    },
    // 失去焦点的事件--切换为查看模式， 展示span
    toLook(row) {
      // 如果属性值为空，不能作为新的属性值，需要给用户提示，让他输入一个其他的属性值
      if (row.valueName.trim() === '') {
        this.$message('请你输入一个正常的属性值')
        return
      }
      // 新增的属性值不能与已有的属性值重复
      const isRepat = this.attrInfo.attrValueList.some(item => {
        // 需要将row从数组里面判断的时候去除 剔除自己再进行判断，否则自己与自己判断永远都是重复的
        // row是最新新增的属性值【数组的最后一项元素】
        // 判断的时候，需要把已有的数组当中新增的这个属性值去除后再判断
        if (row !== item) {
          return row.valueName === item.valueName
        }
      })
      // console.log('是否重复', isRepat)
      if (isRepat) return
      // row这个形参：是当前用户添加的最新的属性值
      // 当前编辑模式变为查看模式（让input消失，显示span）
      row.flag = false
    },
    // 点击span的回调，变为编辑模式
    toEdit(row, index) {
      row.flag = true
      // 获取input节点，实现自动聚焦
      // 需要注意：点击span的时候，切换为input变为编辑模式，但是需要注意的是，对于浏览器而言，页面重绘与重排耗时间
      // 点击span的时候，重绘和重排一个input需要耗费时间，因此我们不可能一点击span就马上获取到input
      // 用$nextTick(),当节点渲染完毕之后，会执行一次
      this.$nextTick(() => {
        // 获取相应的input表单元素实现聚焦
        this.$refs[index].focus()
      })
    },
    // 气泡确认框按钮的回调
    // 最新版本的Element-ui是2.15.6，我们引入的Element-ui版本为2.13.2
    deleteAttrValue(index) {
      // console.log(111)
      // 当前这个删除属性在的操作是不需要发请求的
      this.attrInfo.attrValueList.splice(index, 1)
    },
    // 保存按钮：进行添加属性或者修改属性的操作
    async addOrUpdateAttr() {
      // 整理参数: 1.如果用户添加很多空的属性值，不需要提交给服务器；2.服务器不需要提交flag字段
      this.attrInfo.attrValueList = this.attrInfo.attrValueList.filter(item => {
        // 返回一个新的数组， 过滤掉属性值不是空的
        if (item.valueName !== '') {
          // 有属性值的，同时去掉flag
          delete item.flag
          return true
        }
      })
      try {
        await this.$API.attr.reqAddOrUpdateAttr(this.attrInfo)
        this.isShowTable = true
        this.$message.success('保存成功')
        this.getAttrList()
        // this.$router.go(-1)
      } catch (error) {
        this.$message.error(error.message)
      }
    },
    // 删除属性
    deleteAttr(row) {
      // console.log('...', row)
      this.$confirm(`你确定删除${row.attrName}?`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(async() => {
        const result = await this.$API.attr.reqDeleteAttr(row.id)
        if (result.code === 200) {
          this.$message({
            type: 'success',
            message: '删除成功!'
          })
        }
        // 再次获取品牌列表数据
        this.getAttrList()
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消删除'
        })
      })
    }

  }
}
</script>
<style lang="">
</style>
